"""
用户端API - 小说列表和详情
"""
import json
import os
import shutil
import time

import redis
from fastapi import APIRouter, Query, HTTPException, Header, Form, UploadFile, File
from pydantic import BaseModel
from typing import Optional, List

from qiniu import Auth
from requests import Response
from tortoise.models import Model

from app.page.lx import main
from models.m import Novel, Chapter, NovelCategory, AuthorVerification, AuthorVerificationStatus, User
from tortoise.expressions import Q
from tool.jwt_utils import verify_token, get_current_user
from tool.sessing import Settings

redis_create = redis.Redis(host="127.0.0.1", port= 6379, db=0)


page_user = APIRouter()






# ==================== 响应模型 ====================

class NovelListItem(BaseModel):
    """小说列表项"""
    id: int
    title: str
    author: str
    cover_url: Optional[str] = None
    description: Optional[str] = None
    category_name: str
    word_count: int
    chapter_count: int
    view_count: int
    collect_count: int
    rating: float
    status: str
    is_featured: bool
    tags: Optional[List[str]] = None
    
    class Config:
        from_attributes = True


class ChapterListItem(BaseModel):
    """章节列表项"""
    id: int
    title: str
    chapter_number: int
    word_count: int
    view_count: int
    is_vip: bool
    
    class Config:
        from_attributes = True


class NovelDetailResponse(BaseModel):
    """小说详情响应"""
    id: int
    title: str
    author: str
    cover_url: Optional[str] = None
    description: Optional[str] = None
    category_name: str
    tags: Optional[List[str]] = None
    status: str
    word_count: int
    chapter_count: int
    view_count: int
    collect_count: int
    rating: float
    is_vip: bool
    chapters: List[ChapterListItem]
    
    class Config:
        from_attributes = True


# ==================== 小说列表接口 ====================

@page_user.get("/novels", summary="获取小说列表", tags=["小说"])
async def get_novel_list(
    page: int = Query(1, ge=1, description="页码"),
    page_size: int = Query(10, ge=1, le=100, description="每页数量"),
    category_id: Optional[int] = Query(None, description="分类ID"),
    keyword: Optional[str] = Query(None, description="搜索关键词"),
    status: Optional[int] = Query(None, description="状态（1-连载中，2-已完结）"),
    is_featured: Optional[bool] = Query(None, description="是否推荐")
):
    """
    获取小说列表
    
    - 支持分页
    - 支持按分类筛选
    - 支持关键词搜索
    - 支持按状态筛选
    - 支持推荐筛选
    """
    try:
        # 构建查询条件
        query = Novel.filter(audit_status=2)  # 只返回审核通过的
        
        if category_id:
            query = query.filter(category_id=category_id)
        
        if status:
            query = query.filter(status=status)
        
        if is_featured is not None:
            query = query.filter(is_featured=is_featured)
        
        if keyword:
            # 关键字同时匹配 书名/作者/简介
            query = query.filter(
                Q(title__icontains=keyword) |
                Q(author__icontains=keyword) |
                Q(description__icontains=keyword)
            )
        
        # 获取总数
        total = await query.count()
        
        # 分页查询
        novels = await query.order_by('-created_at')\
                           .offset((page - 1) * page_size)\
                           .limit(page_size)\
                           .prefetch_related('category')
        
        # 转换为响应模型
        novel_list = []
        for novel in novels:
            novel_list.append(NovelListItem(
                id=novel.id,
                title=novel.title,
                author=novel.author,
                cover_url=novel.cover_url,
                description=novel.description,
                category_name=novel.category.name,
                word_count=novel.word_count,
                chapter_count=novel.chapter_count,
                view_count=novel.view_count,
                collect_count=novel.collect_count,
                rating=float(novel.rating),
                status="连载中" if novel.status == 1 else "已完结",
                is_featured=novel.is_featured,
                tags=novel.tags
            ))
        
        return {
            "code": 200,
            "message": "获取成功",
            "data": {
                "list": novel_list,
                "pagination": {
                    "total": total,
                    "page": page,
                    "page_size": page_size,
                    "total_pages": (total + page_size - 1) // page_size
                }
            }
        }
    
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"获取小说列表失败: {str(e)}")


# ==================== 小说详情接口 ====================

@page_user.get("/novels/{novel_id}", summary="获取小说详情", tags=["小说"])
async def get_novel_detail(novel_id: int):
    """
    获取小说详情
    
    - 包含小说基本信息
    - 包含所有章节列表
    """
    try:
        # 获取小说
        novel = await Novel.get_or_none(id=novel_id).prefetch_related('category')
        
        if not novel:
            raise HTTPException(status_code=404, detail="小说不存在")
        
        # 检查是否审核通过
        if novel.audit_status != 2:
            raise HTTPException(status_code=403, detail="小说未通过审核")
        
        # 获取章节列表
        chapters = await Chapter.filter(novel_id=novel_id)\
                               .order_by('chapter_number')\
                               .all()
        
        chapter_list = []
        for chapter in chapters:
            chapter_list.append(ChapterListItem(
                id=chapter.id,
                title=chapter.title,
                chapter_number=chapter.chapter_number,
                word_count=chapter.word_count,
                view_count=chapter.view_count,
                is_vip=chapter.is_vip
            ))
        
        # 构建响应
        return {
            "code": 200,
            "message": "获取成功",
            "data": {
                "id": novel.id,
                "title": novel.title,
                "author": novel.author,
                "cover_url": novel.cover_url,
                "description": novel.description,
                "category_name": novel.category.name,
                "tags": novel.tags,
                "status": "连载中" if novel.status == 1 else "已完结",
                "word_count": novel.word_count,
                "chapter_count": novel.chapter_count,
                "view_count": novel.view_count,
                "collect_count": novel.collect_count,
                "rating": float(novel.rating),
                "is_vip": novel.is_vip,
                "chapters": chapter_list
            }
        }
    
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"获取小说详情失败: {str(e)}")


# ==================== 章节内容接口 ====================

@page_user.get("/novels/{novel_id}/chapters/{chapter_id}", summary="获取章节内容", tags=["小说"])
async def get_chapter_content(novel_id: int, chapter_id: int):
    """
    获取章节内容
    
    - 返回完整的章节文本内容
    """
    try:
        # 获取章节
        chapter = await Chapter.get_or_none(id=chapter_id, novel_id=novel_id)
        
        if not chapter:
            raise HTTPException(status_code=404, detail="章节不存在")
        
        # 检查章节是否审核通过
        if chapter.audit_status != 2:
            raise HTTPException(status_code=403, detail="章节未通过审核")
        
        # 返回章节内容
        return {
            "code": 200,
            "message": "获取成功",
            "data": {
                "id": chapter.id,
                "novel_id": novel_id,
                "title": chapter.title,
                "chapter_number": chapter.chapter_number,
                "content": chapter.content,
                "word_count": chapter.word_count,
                "is_vip": chapter.is_vip
            }
        }
    
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"获取章节内容失败: {str(e)}")


# ==================== 分类列表接口 ====================

@page_user.get("/categories", summary="获取分类列表", tags=["小说"])
async def get_categories():
    """
    获取所有小说分类
    """
    try:
        categories = await NovelCategory.filter(is_active=True).all()
        
        category_list = []
        for cat in categories:
            # 获取该分类下的小说数量
            novel_count = await Novel.filter(category_id=cat.id, audit_status=2).count()
            
            category_list.append({
                "id": cat.id,
                "name": cat.name,
                "slug": cat.slug,
                "description": cat.description,
                "novel_count": novel_count
            })
        
        return {
            "code": 200,
            "message": "获取成功",
            "data": category_list
        }
    
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"获取分类列表失败: {str(e)}")


# ==================== 我的作品列表 ====================

@page_user.get("/my/novels", summary="获取当前作者的作品列表", tags=["小说"])
async def get_my_novels(authorization: str | None = Header(None)):
    """
    根据 Authorization Bearer token 解析当前用户ID，返回其名下作品列表。
    返回字段与前端作者页表格对齐：id、title、category_name、status、audit_status、
    word_count、view_count、collect_count、is_featured。
    """
    try:
        if not authorization or not authorization.lower().startswith("bearer "):
            raise HTTPException(status_code=401, detail="未授权：缺少Bearer Token")

        token = authorization.split(" ", 1)[1].strip()
        payload = verify_token(token)
        if not payload or not payload.get("user_id"):
            raise HTTPException(status_code=401, detail="无效或过期的Token")

        user_id = payload["user_id"]

        novels = await Novel.filter(user_id=user_id).order_by("-updated_at").prefetch_related("category")

        items = []
        for n in novels:
            items.append({
                "id": n.id,
                "title": n.title,
                "category_name": n.category.name if n.category_id else "",
                "status": int(n.status),
                "audit_status": int(n.audit_status),
                "word_count": n.word_count,
                "view_count": n.view_count,
                "collect_count": n.collect_count,
                "is_featured": n.is_featured,
            })

        return {
            "code": 200,
            "message": "获取成功",
            "data": {
                "list": items,
                "total": len(items)
            }
        }

    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=f"获取我的作品失败: {str(e)}")


# # 作者申请表
# @page_user.post("/register", summary="注册作者", tags=["用户"])
# async def register_author(
#         pen_name: str = Form(...),
#         introduction: Optional[str] = Form(None),
#         sample_work: Optional[str] = Form(None),
#         id_card_front_file: UploadFile = File(...),
#         id_card_back_file: Optional[UploadFile] = File(None),
#         authorization: str | None = Header(None)):
#     """
#     注册作者接口
#
#     Args:
#         pen_name: 笔名
#         introduction: 作者简介
#         sample_work: 作品样例
#         id_card_front_file: 身份证正面照片文件
#         id_card_back_file: 身份证反面照片文件（可选）
#
#     Returns:
#         注册结果
#     """
    # 1. 验证Token并获取用户
    # if not authorization or not authorization.lower().startswith("bearer "):
    #     raise HTTPException(status_code=401, detail="未授权：缺少Bearer Token")
    #
    # token = authorization.split(" ", 1)[1].strip()
    # user_id = get_current_user(token)
    # if not user_id:
    #     raise HTTPException(status_code=401, detail="无效或过期的Token")
    #
    # user = await User.get_or_none(id=user_id)
    # if not user:
    #     raise HTTPException(status_code=404, detail="用户不存在")
    #
    # # 2. 检查是否已提交过申请
    # existing_verification = await AuthorVerification.get_or_none(user_id=user_id)
    #
    # if existing_verification:
    #     raise HTTPException(status_code=400, detail="该用户已提交过作者认证申请")
    #
    # # 3. 校验文件格式和大小
    # allowed_extensions = {'.jpg', '.jpeg', '.png'}
    # front_ext = os.path.splitext(id_card_front_file.filename)[1].lower()
    # if front_ext not in allowed_extensions:
    #     raise HTTPException(status_code=400, detail="身份证正面照片格式不支持，仅支持jpg/png")
    #
    # # 检查文件大小（最大5MB）
    # max_size = 5 * 1024 * 1024
    # if id_card_front_file.size and id_card_front_file.size > max_size:
    #     raise HTTPException(status_code=400, detail="身份证正面照片文件过大，最大5MB")
    #
    # # 4. 处理身份证正面照片 - 上传到七牛云并OCR识别
    # front_filename = f"front_{user_id}_{int(time.time())}.jpg"
    # real_name = ""
    # id_card = ""
    #
    # try:
    #     # 读取文件内容用于上传到七牛云
    #     id_card_front_file.file.seek(0)
    #     file_data = await id_card_front_file.read()
    #
    #     # 获取七牛云上传凭证
    #     access_key = 'IPzQQFeLOA4fPDWzUTQQX7eJ4OcAfyzDyR3A3HN6'
    #     secret_key = 'hi1t3IWhYxp5H-SI7sJnFLHR9x_oUt8mFeYtuz6z'
    #     bucket_name = '653ef'
    #
    #     # 构建鉴权对象并生成上传token
    #     q = Auth(access_key, secret_key)
    #     token = q.upload_token(bucket_name, front_filename, 3600)
    #
    #     # 上传到七牛云
    #     from qiniu import put_data
    #     ret, info = put_data(token, front_filename, file_data)
    #
    #     if info.status_code != 200:
    #         raise HTTPException(status_code=500, detail="身份证正面照片上传七牛云失败")
    #
    #     # 七牛云URL
    #     front_url = f"http://t4y377zln.hb-bkt.clouddn.com/{front_filename}"
    #
    #
    #     # 7. 处理身份证反面照片（可选）- 上传到七牛云
    #     if id_card_back_file:
    #         back_ext = os.path.splitext(id_card_back_file.filename)[1].lower()
    #         if back_ext not in allowed_extensions:
    #             raise HTTPException(status_code=400, detail="身份证反面照片格式不支持，仅支持jpg/png")
    #
    #         if id_card_back_file.size and id_card_back_file.size > max_size:
    #             raise HTTPException(status_code=400, detail="身份证反面照片文件过大，最大5MB")
    #
    #         back_filename = f"back_{user_id}_{int(time.time())}.jpg"
    #
    #         try:
    #             # 读取文件内容用于上传到七牛云
    #             id_card_back_file.file.seek(0)
    #             file_data = await id_card_back_file.read()
    #
    #             # 生成上传token
    #             q = Auth(access_key, secret_key)
    #             token = q.upload_token(bucket_name, back_filename, 3600)
    #
    #             # 上传到七牛云
    #             from qiniu import put_data
    #             ret, info = put_data(token, back_filename, file_data)
    #
    #             if info.status_code == 200:
    #                 id_card_back_url = f"http://t4y377zln.hb-bkt.clouddn.com/{back_filename}"
    #             else:
    #                 print(f"身份证反面照片上传七牛云失败: {info.error}")
    #
    #         except Exception as e:
    #             # 反面照片失败不影响主流程，但记录错误
    #             print(f"上传身份证反面照片到七牛云失败: {str(e)}")
    #
    #
    #
    #     register_data = {
    #         "pen_name": pen_name,
    #         "introduction": introduction,
    #         "sample_work": sample_work,
    #         "id_card_front_file": front_url,   #正面七牛云图片地址
    #         "id_card_back_file":id_card_back_url , #侧面七牛云图片地址
    #         "authorization": authorization
    #     }
    #
    #     redis.lpush("user/register/sfz", json.dumps(register_data))
    #
    #     # 5. OCR识别身份证正面
    #     try:
    #         # 调用OCR时传入七牛云URL
    #         img_result = main(front_url)  # 传入七牛云URL
    #
    #         if not img_result or "words_result" not in img_result:
    #             raise HTTPException(status_code=400, detail="身份证正面OCR识别失败：无法解析结果")
    #
    #         # 检查图片质量状态
    #         image_status = img_result.get("image_status","")
    #         if image_status:
    #             status_messages = {
    #                 "over_exposure": "身份证照片曝光过度，请重新拍摄清晰的照片",
    #                 "under_exposure": "身份证照片曝光不足，请重新拍摄清晰的照片",
    #                 "blurred": "身份证照片模糊不清，请重新拍摄清晰的照片",
    #                 "normal": ""  # 正常状态
    #             }
    #             if image_status in status_messages and image_status != "normal":
    #                 raise HTTPException(status_code=400, detail=status_messages[image_status])
    #             elif image_status not in status_messages:
    #                 # 其他未知状态
    #                 raise HTTPException(status_code=400, detail=f"身份证照片质量问题：{image_status}，请重新拍摄清晰的照片")
    #
    #         # 提取姓名和身份证号
    #         name_info = img_result.get("words_result", {}).get("姓名", {})
    #         id_info = img_result.get("words_result", {}).get("公民身份号码", {})
    #
    #         real_name = name_info.get("words", "").strip() if name_info else ""
    #         id_card = id_info.get("words", "").strip() if id_info else ""
    #
    #         if not real_name:
    #             raise HTTPException(status_code=400, detail="身份证正面照片中未识别到姓名，请确保照片清晰完整")
    #
    #         if not id_card:
    #             raise HTTPException(status_code=400, detail="身份证正面照片中未识别到身份证号，请确保照片清晰完整且未遮挡号码区域")
    #
    #     except HTTPException:
    #         raise
    #     except Exception as e:
    #         raise HTTPException(status_code=400, detail=f"身份证正面OCR识别失败: {str(e)}")
    #
    # except HTTPException:
    #     # 重新抛出HTTPException，避免被外层捕获为500错误
    #     raise
    # except Exception as e:
    #     raise HTTPException(status_code=500, detail=f"处理身份证正面照片失败: {str(e)}")
    #
    # # 6. 创建认证记录
    # verification = AuthorVerification(
    #     user_id=user_id,
    #     real_name=real_name,
    #     id_card=id_card,
    #     pen_name=pen_name,
    #     introduction=introduction,
    #     sample_work=sample_work,
    #     status=AuthorVerificationStatus.PENDING,
    #     id_card_back_url = id_card_back_url
    # )
    #
    # # 设置正面照片URL
    # verification.id_card_front_url = front_url
    #
    #
    # # 8. 保存到数据库
    # await verification.save()
    #
    # return {
    #     "code": 200,
    #     "message": "作者认证申请提交成功",
    #     "data": {
    #         "verification_id": verification.id,
    #         "real_name": real_name,  # 返回识别出的真实姓名
    #         "id_card": id_card[:6] + "********" + id_card[-4:]  # 脱敏处理后返回身份证号
    #     }
    # }


# 七牛云图片上传


#查询用户的作者认证是否还在审核中




@page_user.get("/author_verification", summary="查询用户的作者认证是否还在审核中", tags=["用户"])
async def query_author_verification(self, request):
    user_id = request.user_id
    verification = await AuthorVerification.get_or_none(user_id=user_id)
    if verification.status == AuthorVerificationStatus.PENDING:
        return {
            "code": 10000,
            "message": "正在审核",
            "data": None
        }
    #申请通过修改用户角色
    if verification.status == AuthorVerificationStatus.APPROVED:
        user = await User.get_or_none(id=user_id)
        user(role = 2)
        user.save()
        return {
            "code":1000,
            "message":"申请通过,你现在是作家了",
            "data":{user}
        }
    #申请拒绝
    if verification.status == AuthorVerificationStatus.REJECTED:
        return {
            "code":1000,
            "message":f"申请被拒绝，原因{verification.reject_reason}",
            "data":None
        }
    return {
        "code":1000,
        "message":"申请正在处理中",
        "data":None
    }






@page_user.get("/qny_img", summary="七牛云图片上传", tags=["用户"])
async  def qny_img(self, request):
    # 需要填写你的 Access Key 和 Secret Key
    access_key = 'IPzQQFeLOA4fPDWzUTQQX7eJ4OcAfyzDyR3A3HN6'
    secret_key = 'hi1t3IWhYxp5H-SI7sJnFLHR9x_oUt8mFeYtuz6z'
    # 构建鉴权对象
    q = Auth(access_key, secret_key)
    # 要上传的空间
    bucket_name = '653ef'

    # 3600为token过期时间，秒为单位。3600等于一小时
    token = q.upload_token(bucket_name)
    return Response({"code": 10000, 'data': token})